package com.baijiayun.live.ui

import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import com.baijiayun.live.ui.base.BaseViewModel
import com.baijiayun.live.ui.base.RouterViewModel
import com.baijiayun.live.ui.speakerlist.item.SwitchableStatus
import com.baijiayun.live.ui.toolbox.questionanswer.QuestionStatus
import com.baijiayun.live.ui.utils.JsonObjectUtil
import com.baijiayun.livecore.context.LPConstants
import com.baijiayun.livecore.context.LPError
import com.baijiayun.livecore.listener.OnPhoneRollCallListener
import com.baijiayun.livecore.models.*
import com.baijiayun.livecore.models.broadcast.LPMainScreenNoticeModel
import com.baijiayun.livecore.models.imodels.*
import com.baijiayun.livecore.viewmodels.impl.LPSpeakQueueViewModel
import com.google.gson.JsonObject
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
import kotlin.random.Random

class LiveRoomViewModel(val routerViewModel: RouterViewModel) : BaseViewModel() {
    /**
     * 大小班切换
     */
    val classSwitch = MutableLiveData<Unit>()
    val forbidChatAllModel = MutableLiveData<LPRoomForbidChatResult>()

    /**
     * 媒体状态
     */
    val mediaStatus = MutableLiveData<MediaStatus>()

    /**
     * 媒体 类型
     */
    var extraMediaChange = MutableLiveData<Pair<LPConstants.MediaSourceType, Boolean>>()

    /**
     * toast消息
     */
    val showToast = MutableLiveData<String>()
    //
    val reportAttention = MutableLiveData<Unit>()
    //
    var teacherVideoOn = false
    var teacherAudioOn = false
    var counter = 0

    override fun subscribe() {
        with(routerViewModel) {
            liveRoom.observableOfKickOut.observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPError>() {
                    override fun onNext(lpError: LPError) {
                        actionShowError.value = lpError
                    }
                })
            liveRoom.speakQueueVM.observableOfMixModePresenterChange.observeOn(AndroidSchedulers.mainThread())
                .ofType(LPUserModel::class.java)
                .subscribe(object : DisposingObserver<LPUserModel>() {
                    override fun onNext(t: LPUserModel) {
                        routerViewModel.notifyMixModePresenterChange.value = t
                    }
                })
            liveRoom.observableOfClassStart.observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<Int>() {
                    override fun onNext(t: Int) {
                        isClassStarted.value = true
                    }
                })
            liveRoom.observableOfClassEnd.observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<Int>() {
                    override fun onNext(t: Int) {
                        if (!isAdmin(liveRoom) && liveRoom.isShowEvaluation) {
                            routerViewModel.showEvaDlg.value = true
                        }
                        awardRecord.clear()
                        classEnd.value = Unit
                        answerEnd.value = null
                        isClassStarted.value = false
                        teacherVideoOn = false
                        teacherAudioOn = false
                    }
                })
            liveRoom.observableOfClassSwitch.delay(Random.nextInt(2) + 1L, TimeUnit.SECONDS)
                .subscribe(object : DisposingObserver<Int>() {
                    override fun onNext(t: Int) {
                        classSwitch.postValue(Unit)
                    }
                })
            liveRoom.observableOfForbidAllChatStatus
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPRoomForbidChatResult>() {
                    override fun onNext(t: LPRoomForbidChatResult) {
                        if (counter == 0) {
                            counter++
                            return
                        }
                        forbidChatAllModel.value = t
                    }
                })

            if (liveRoom.currentUser.type != LPConstants.LPUserType.Teacher) {
                liveRoom.speakQueueVM.observableOfMediaPublish
                    .filter { !liveRoom.isTeacherOrAssistant && it.user.type == LPConstants.LPUserType.Teacher }
                    .filter { liveRoom.isClassStarted }
                    .filter { !liveRoom.speakQueueVM.isMixModeOn && it.user.userId != LPSpeakQueueViewModel.FAKE_MIX_STREAM_USER_ID }
                    .throttleFirst(500, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<IMediaModel>() {
                        override fun onNext(iMediaModel: IMediaModel) {
                            if (iMediaModel.mediaSourceType == LPConstants.MediaSourceType.ExtCamera ||
                                iMediaModel.mediaSourceType == LPConstants.MediaSourceType.ExtScreenShare ||
                                iMediaModel.mediaSourceType == LPConstants.MediaSourceType.MainScreenShare
                            ) {
                                extraMediaChange.value =
                                    iMediaModel.mediaSourceType to iMediaModel.isVideoOn
                                return
                            }
                            if (iMediaModel.isVideoOn && iMediaModel.isAudioOn) {
                                if (!teacherVideoOn && !teacherAudioOn) {
                                    mediaStatus.value = MediaStatus.VIDEO_AUDIO_ON
                                } else if (!teacherAudioOn) {
                                    mediaStatus.value = MediaStatus.AUDIO_ON
                                } else if (!teacherVideoOn) {
                                    mediaStatus.value = MediaStatus.VIDEO_ON
                                }
                            } else if (iMediaModel.isVideoOn) {
                                if (teacherAudioOn && teacherVideoOn) {
                                    mediaStatus.value = MediaStatus.AUDIO_CLOSE
                                } else if (!teacherVideoOn) {
                                    mediaStatus.value = MediaStatus.VIDEO_ON
                                }
                            } else if (iMediaModel.isAudioOn) {
                                if (teacherAudioOn && teacherVideoOn) {
                                    mediaStatus.value = MediaStatus.VIDEO_CLOSE
                                } else if (!teacherAudioOn) {
                                    mediaStatus.value = MediaStatus.AUDIO_ON
                                }
                            } else {
                                mediaStatus.value = MediaStatus.VIDEO_AUDIO_CLOSE
                            }
                            setTeacherMedia(iMediaModel)
                        }
                    })
                liveRoom.observableOfUserIn
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<IUserInModel>() {
                        override fun onNext(iUserInModel: IUserInModel) {
                            if (iUserInModel.user.type == LPConstants.LPUserType.Teacher) {
                                showTeacherIn.value = true
                            }
                            if (iUserInModel.user.userId == liveRoom.speakQueueVM.presenter) {
                                showPresenterIn.value = Unit
                            }
                        }
                    })

                liveRoom.onlineUserVM.observableOfUserOut
                    .filter { it.type == LPConstants.LPUserType.Teacher }
                    .subscribe(object : DisposingObserver<IUserModel>() {
                        override fun onNext(userModel: IUserModel) {
                            showTeacherIn.value = false
                        }
                    })
                //小测
                liveRoom.quizVM.observableOfQuizStart
                    .filter { !liveRoom.isTeacherOrAssistant && !liveRoom.isGroupTeacherOrAssistant }
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPJsonModel>() {
                        override fun onNext(lpJsonModel: LPJsonModel) {
                            quizStatus.value = RouterViewModel.QuizStatus.START to lpJsonModel
                        }
                    })
                //中途打开
                liveRoom.quizVM.observableOfQuizRes
                    .filter { !liveRoom.isTeacherOrAssistant && !liveRoom.isGroupTeacherOrAssistant && it.data != null }
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPJsonModel>() {
                        override fun onNext(lpJsonModel: LPJsonModel) {
                            val quizId = JsonObjectUtil.getAsString(lpJsonModel.data, "quiz_id")
                            var solutionStatus = false
                            if (!lpJsonModel.data.has("solution")) {
                                //没有solution
                                solutionStatus = true
                            } else if (lpJsonModel.data.getAsJsonObject("solution").entrySet()
                                    .isEmpty()
                            ) {
                                //"solution":{}
                                solutionStatus = true
                            } else if (lpJsonModel.data.getAsJsonObject("solution").isJsonNull) {
                                //"solution":"null"
                                solutionStatus = true
                            }
                            val endFlag = lpJsonModel.data.get("end_flag").getAsInt() == 1
                            //quizid非空、solution是空、没有结束答题 才弹窗
                            if (!TextUtils.isEmpty(quizId) && solutionStatus && !endFlag) {
                                quizStatus.value = RouterViewModel.QuizStatus.RES to lpJsonModel
                            }
                        }
                    })
                //小测结束
                liveRoom.quizVM.observableOfQuizEnd
                    .filter { !liveRoom.isTeacherOrAssistant && !liveRoom.isGroupTeacherOrAssistant }
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPJsonModel>() {
                        override fun onNext(lpJsonModel: LPJsonModel) {
                            quizStatus.value = RouterViewModel.QuizStatus.END to lpJsonModel
                        }
                    })
                //发答案
                liveRoom.quizVM.observableOfQuizSolution
                    .filter { !liveRoom.isTeacherOrAssistant && !liveRoom.isGroupTeacherOrAssistant }
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPJsonModel>() {
                        override fun onNext(lpJsonModel: LPJsonModel) {
                            quizStatus.value = RouterViewModel.QuizStatus.SOLUTION to lpJsonModel
                        }
                    })
                liveRoom.toolBoxVM.observableOfBJTimerEnd
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<Boolean>() {
                        override fun onNext(boolean: Boolean) {
                            showTimer.value = false to LPBJTimerModel()
                        }
                    })
                liveRoom.toolBoxVM.observableOfAttentionDetection
                    .observeOn(AndroidSchedulers.mainThread())
                    .filter { !liveRoom.isTeacherOrAssistant && !liveRoom.isGroupTeacherOrAssistant }
                    .subscribe(object : DisposingObserver<LPJsonModel>() {
                        override fun onNext(t: LPJsonModel) {
                            reportAttention.value = Unit
                        }
                    })
                liveRoom.toolBoxVM.observableOfAttentionAlert
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<String>() {
                        override fun onNext(content: String) {
                            showToast.value = content
                        }
                    })
            }
            liveRoom.toolBoxVM.observableOfBJTimerStart
                .mergeWith(liveRoom.toolBoxVM.observableOfBJTimerPause)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPBJTimerModel>() {
                    override fun onNext(lpbjTimerModel: LPBJTimerModel) {
                        showTimer.value = true to lpbjTimerModel
                    }
                })
            liveRoom.toolBoxVM.observableOfAnswerRacerStart
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPAnswerRacerStartModel>() {
                    override fun onNext(lpAnswerRacerStartModel: LPAnswerRacerStartModel) {
                        responderStart.value = lpAnswerRacerStartModel
                    }
                })
            liveRoom.toolBoxVM.observableOfAnswerRacerEnd
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPAnswerRacerEndModel>() {
                    override fun onNext(lpAnswerRacerEndModel: LPAnswerRacerEndModel) {
                        responderEnd.value = lpAnswerRacerEndModel
                    }

                })
            liveRoom.observableOfAnnouncementChange
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<IAnnouncementModel>() {
                    override fun onNext(t: IAnnouncementModel) {
                        if (!t.link.isNullOrEmpty() || !t.content.isNullOrEmpty()) {
                            routerViewModel.actionShowAnnouncementFragment.value = true
                        }
                    }
                })
            liveRoom.requestAnnouncement()
            liveRoom.observableOfRedPacket.observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPRedPacketModel>() {
                    override fun onNext(lpRedPacketModel: LPRedPacketModel) {
                        action2RedPacketUI.value = true to lpRedPacketModel
                    }
                })

            if (isAdmin(liveRoom)) {
                liveRoom.observableOfSpeakInvite.observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPSpeakInviteModel>() {
                        override fun onNext(t: LPSpeakInviteModel) {
                            if (t.invite == 1) {
                                routerViewModel.invitingUserIds.add(t.to)
                            } else {
                                routerViewModel.invitingUserIds.remove(t.to)
                                routerViewModel.timeOutStart.value = t.to to false
                            }
                        }
                    })
                liveRoom.observableOfSpeakInviteRes.observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<LPSpeakInviteConfirmModel>() {
                        override fun onNext(t: LPSpeakInviteConfirmModel) {
                            routerViewModel.invitingUserIds.remove(t.userId)
                            routerViewModel.timeOutStart.value = t.userId to false
                        }
                    })
                liveRoom.observableOfForbidList.observeOn(AndroidSchedulers.mainThread())
                    .map { it.userList }
                    .flatMap { Observable.fromIterable(it) }
                    .subscribe(object : DisposingObserver<LPForbidUserModel>() {
                        override fun onNext(lpForbidUserModel: LPForbidUserModel) {
                            if (lpForbidUserModel.duration > 0) {
                                routerViewModel.forbidChatUserNums.add(lpForbidUserModel.number)
                            } else {
                                routerViewModel.forbidChatUserNums.remove(lpForbidUserModel.number)
                            }
                        }
                    })
                liveRoom.observableOfForbidChat.observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : DisposingObserver<IForbidChatModel>() {
                        override fun onNext(t: IForbidChatModel) {
                            if (t.duration > 0) {
                                routerViewModel.forbidChatUserNums.add(t.forbidUser.number)
                            } else {
                                routerViewModel.forbidChatUserNums.remove(t.forbidUser.number)
                            }
                        }
                    })
                liveRoom.requestForbidList()
            }

            liveRoom.observableOfBroadcast.mergeWith(liveRoom.observableOfBroadcastCache)
                .filter { !liveRoom.isTeacherOrAssistant }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<LPKVModel>() {
                    override fun onNext(t: LPKVModel) {
                        when (t.key) {
                            "custom_webpage" -> {
                                if (t.value is JsonObject) {
                                    val webpageJsonObject = t.value as JsonObject
                                    when (webpageJsonObject.get("action").asString) {
                                        "student_open_webpage" -> {
                                            routerViewModel.actionShowWebpage.value =
                                                webpageJsonObject.get("url").asString
                                        }
                                        "student_close_webpage" -> {
                                            routerViewModel.actionCloseWebpage.value = ""
                                        }
                                    }
                                }
                            }
                        }
                    }
                })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfLottery
                .observeOn(AndroidSchedulers.mainThread())
                //抽奖只有学生参与，试听不参与
                .filter { liveRoom.currentUser.type == LPConstants.LPUserType.Student }
                .subscribe {
                    action2Lottery.value = it
                })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfCommandLotteryStart
                .observeOn(AndroidSchedulers.mainThread())
                .filter { liveRoom.currentUser.type == LPConstants.LPUserType.Student }
                .subscribe {
                    actionCommandLotteryStart.value = it
                })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfQuestionPub
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (isAdmin(liveRoom)) {
                        routerViewModel.hasNewQa.value = true
                    } else {
                        //学生icon问答红点提示，别人的只取已发布，自己的所有状态
                        if (it.status and QuestionStatus.QuestionPublished.status != 0) {
                            routerViewModel.hasNewQaPublished.value = true
                            routerViewModel.hasNewQa.value = true
                        } else {
                            if (it.owner == liveRoom.currentUser.number) {
                                routerViewModel.hasNewQa.value = true
                            }
                        }
                    }
                })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfQuestionSendRes
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (isAdmin(liveRoom)) {
                        routerViewModel.hasNewQa.value = true
                    } else {
                        if (it.status and QuestionStatus.QuestionPublished.status != 0) {
                            routerViewModel.hasNewQaPublished.value = true
                            routerViewModel.hasNewQa.value = true
                        } else {
                            if (it.from.number == liveRoom.currentUser.number) {
                                routerViewModel.hasNewQa.value = true
                            }
                        }
                    }
                })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfComponentDestroy
                .filter {
                    liveRoom.currentUser.type == LPConstants.LPUserType.Teacher
                            || liveRoom.currentUser.type == LPConstants.LPUserType.Assistant
                }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    routerViewModel.answerEnd.value = it
                }
            )
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfAnswerStart
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    answerStart.value = it
                })
            //点名
            liveRoom.toolBoxVM.setOnRollCallListener(object : OnPhoneRollCallListener {
                override fun onRollCall(
                    time: Int,
                    rollCallListener: OnPhoneRollCallListener.RollCall
                ) {
                    showRollCall.value = time to rollCallListener
                }

                override fun onRollCallTimeOut() {
                    dismissRollCall.value = false
                }
            })
            compositeDisposable.add(liveRoom.toolBoxVM.observableOfRollCallResult
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    actionRollCallResult.value = it
                })

            liveRoom.observableOfMainScreenNotice.observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : DisposingObserver<List<LPMainScreenNoticeModel>>() {
                    override fun onNext(noticeModelList: List<LPMainScreenNoticeModel>) {
                        action2ShowMainScreenNotice.value = noticeModelList
                    }
                })
        }
    }

    fun registerSyncPPTVideo() {
        routerViewModel.liveRoom.observableOfPPTVideoSwitch
            .filter { !routerViewModel.isLiveWall() }
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : DisposingObserver<Boolean>() {
                override fun onNext(isVideoInMain: Boolean) {
                    switchPPTAndMainVideo(isVideoInMain)
                }
            })
        compositeDisposable.add(routerViewModel.liveRoom.observableOfRoomLayoutSwitch
            .map { it == LPConstants.RoomLayoutMode.GALLERY }
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                routerViewModel.actionRoomLayoutSwitch.value = it
                if (!routerViewModel.liveRoom.isVideoInMain) {
                    switchPPTAndMainVideo(it)
                }
            })
        routerViewModel.actionRoomLayoutSwitch.value = routerViewModel.isLiveWall()
        if (routerViewModel.isLiveWall() && !routerViewModel.liveRoom.isVideoInMain) {
            switchPPTAndMainVideo(true)
        }
    }

    private fun switchPPTAndMainVideo(isVideoInMain: Boolean) {
        //isVideoInMain 是否mainVideo在ppt容器区
        //mainItem 是老师视频（区别于老师视频区）
        //跟随老师切换，但是如果切换的窗口本身在全屏区域则不立即变化
        val mainItem = routerViewModel.mainVideoItem ?: return
        if (isVideoInMain) {
            if (mainItem.switchableStatus == SwitchableStatus.MaxScreen) {
                return
            }
            if (routerViewModel.switch2MaxScreen.value == null) {
                return
            }
            //老师视频切到maxScreen
            mainItem.switchPPTVideoWithoutSync(true)
        } else {
            if (mainItem.switchableStatus != SwitchableStatus.MaxScreen) {
                return
            }
            //老师视频切到mainVideo
            val mainVideoItem = routerViewModel.switch2MainVideo.value ?: return
            mainVideoItem.switchPPTVideoWithoutSync(true)
        }
    }

    fun setTeacherMedia(media: IMediaModel) {
        teacherVideoOn = media.isVideoOn
        teacherAudioOn = media.isAudioOn
    }

    enum class MediaStatus {
        VIDEO_ON, AUDIO_ON, VIDEO_AUDIO_ON, VIDEO_CLOSE, AUDIO_CLOSE, VIDEO_AUDIO_CLOSE
    }
}
